home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / library / __fstat.c < prev    next >
C/C++ Source or Header  |  1995-09-27  |  9KB  |  270 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  __fstat.c,v 1.1.1.1 1994/04/04 04:30:08 amiga Exp
  20.  *
  21.  *  __fstat.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:08  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1993/11/05  21:49:59  mw
  26.  *  "grp/oth-perms,
  27.  *
  28.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36.  
  37. #if __GNUC__ != 2
  38. #define alloca __builtin_alloca
  39. #endif
  40.  
  41. #ifndef ACTION_EXAMINE_FH
  42. #define ACTION_EXAMINE_FH 1034
  43. #endif
  44.  
  45. #ifndef ST_LINKDIR
  46. #define ST_ROOT        1
  47. #define ST_USERDIR    2
  48. #define ST_SOFTLINK    3    /* looks like dir, but may point to a file! */
  49. #define ST_LINKDIR    4    /* hard link to dir */
  50. #define ST_FILE        -3    /* must be negative for FIB! */
  51. #define ST_LINKFILE    -4    /* hard link to file */
  52. #define ST_PIPEFILE    -5    /* for pipes that support ExamineFH */
  53. #endif
  54.  
  55. extern void *alloca ();
  56.  
  57. /************************************************************************/
  58. /*                                                                      */
  59. /*    fstat() function.                                                 */
  60. /*                                                                      */
  61. /************************************************************************/
  62.  
  63. int
  64. __fstat(struct file *f)
  65. {
  66.   long len, pos;
  67.   struct FileInfoBlock *fib;
  68.   struct InfoData *info;
  69.   int omask;
  70.  
  71.   omask = syscall (SYS_sigsetmask, ~0);
  72.   __get_file (f);
  73.  
  74.   /* take special care of NIL:, /dev/null and friends ;-) */
  75.   if (HANDLER_NIL(f))
  76.     {
  77.       f->f_stb.st_mode = S_IFCHR | 0777;
  78.       f->f_stb.st_nlink = 1;
  79.       f->f_stb.st_blksize = ix.ix_fs_buf_factor * 512;
  80.       f->f_stb.st_blocks = 0;
  81.       goto end;
  82.     }
  83.  
  84.   info = alloca (sizeof (*info) + 2);
  85.   info = LONG_ALIGN (info);
  86.   fib  = alloca (sizeof (*fib) + 2);
  87.   fib  = LONG_ALIGN (fib);
  88.     
  89.   __wait_packet (&f->f_sp);
  90.   /* reset the error field */
  91.   LastError (f) = 0;
  92.  
  93.   /* we now have two possibilities.. either the filesystem understands the
  94.    * new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
  95. /*  SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, CTOBPTR(f->f_fh), CTOBPTR(fib));*/
  96.   SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
  97.   __wait_packet (&f->f_sp);
  98.   if (LastResult(f))
  99.     {
  100.       int mode;
  101.  
  102.       f->f_stb.st_nlink = 1; /* always one link entry per file, unless... */
  103.       f->f_stb.st_amode = fib->fib_Protection;
  104.  
  105.       mode = 0;
  106.       if (!(fib->fib_Protection & FIBF_EXECUTE))
  107.         mode |= S_IXUSR;
  108.       else if (fib->fib_Protection & FIBF_SCRIPT)
  109.         mode |= S_IXUSR;
  110.       if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
  111.         mode |= S_IWUSR;
  112.       if (!(fib->fib_Protection & FIBF_READ))
  113.         mode |= S_IRUSR;
  114. #ifdef FIBF_GRP_EXECUTE
  115.       /* FIBF_GRP_EXECUTE requires at least OS3 headers */
  116.       if (fib->fib_Protection & FIBF_GRP_EXECUTE)
  117.         mode |= S_IXGRP;
  118.       if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
  119.         mode |= S_IWGRP;
  120.       if (fib->fib_Protection & FIBF_GRP_READ)
  121.         mode |= S_IRGRP;
  122.       if (fib->fib_Protection & FIBF_OTR_EXECUTE)
  123.         mode |= S_IXOTH;
  124.       if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
  125.         mode |= S_IWOTH;
  126.       if (fib->fib_Protection & FIBF_OTR_READ)
  127.         mode |= S_IROTH;
  128. #endif
  129.  
  130.       switch (fib->fib_DirEntryType)
  131.         {
  132.         case ST_LINKDIR:
  133.           f->f_stb.st_nlink++;  /* we never get more than a link count of two.. */
  134.         case ST_ROOT:
  135.         case ST_USERDIR:
  136.           mode |= S_IFDIR;
  137.           break;
  138.  
  139.         /* at the moment, we NEVER get this entry, since we can't get a lock
  140.          * on a symlink */
  141.         case ST_SOFTLINK:
  142.           mode |= S_IFLNK;
  143.           break;
  144.  
  145.     case ST_PIPEFILE:
  146.       /* don't use S_IFIFO, we don't have a mkfifo() call ! */
  147.       mode |= S_IFCHR;
  148.       break;
  149.  
  150.         case ST_LINKFILE:
  151.           f->f_stb.st_nlink ++;
  152.         case ST_FILE:
  153.         default:
  154.           mode |= S_IFREG;
  155.         }
  156.  
  157.       /* ARGLLLLL !!!
  158.          Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
  159.          don't know yet about ST_PIPEFILE. So console windows claim they're
  160.          plain files... Until this problem is fixed in a majority of
  161.          handlers, do an explicit SEEK here to find those fakers.. */
  162.       LastError(f) = 0;
  163.       SendPacket3(f,__rwport,ACTION_SEEK,f->f_fh->fh_Arg1,0,OFFSET_CURRENT);
  164.       __wait_packet (&f->f_sp);
  165.       if (LastError (f))
  166.         mode = (mode & ~S_IFREG) | S_IFCHR;
  167.  
  168.       f->f_stb.st_mode = mode;
  169.  
  170.       /* support for annotated attributes (cool name ;-)) */
  171.       if (! strncmp (fib->fib_Comment, "!SP!", 4))
  172.         {
  173.           int sp_mode, sp_addr;
  174.  
  175.           if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
  176.             f->f_stb.st_mode = sp_mode;
  177.         }
  178.   
  179.       /* some kind of a default-size for directories... */
  180.       f->f_stb.st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024; 
  181.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  182.       f->f_stb.st_dev = (dev_t)f->f_stb.st_handler; /* trunc to 16 bit */
  183.       f->f_stb.st_ino = fib->fib_DiskKey; 
  184.       f->f_stb.st_atime =
  185.       f->f_stb.st_ctime =
  186.       f->f_stb.st_mtime = (8*365+2)*24*3600 + /* offset to unix-timesystem */
  187.                   fib->fib_Date.ds_Days * 24 * 60 * 60 +
  188.                   fib->fib_Date.ds_Minute * 60 +
  189.                   fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  190.       /* in a try to count the blocks used for filemanagement, we add one for
  191.        * the fileheader. Note, that this is wrong for large files, where there
  192.        * are some extension-blocks as well */
  193.       f->f_stb.st_blocks = fib->fib_NumBlocks + 1;
  194.     }
  195.   else
  196.     {
  197.       /* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
  198.       /* seek to EOF */
  199.       SendPacket3 (f, __rwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
  200.       __wait_packet (&f->f_sp);
  201.       pos = LastResult (f);
  202.       if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
  203.         {
  204.           SendPacket3 (f, __rwport,ACTION_SEEK, f->f_fh->fh_Arg1, 
  205.                    pos, OFFSET_BEGINNING);
  206.           __wait_packet (&f->f_sp);
  207.           len = LastError (f) ? -1 : LastResult (f);
  208.         }
  209.       else
  210.         len = 0;
  211.  
  212.       bzero (&f->f_stb, sizeof(struct stat));
  213.  
  214.       f->f_stb.st_mode = ((len >= 0 && 
  215.                      /* !IsInteractive(CTOBPTR(f->f_fh)) */! f->f_fh->fh_Port)
  216.                      ? S_IFREG : S_IFCHR) | 0777;
  217.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  218.       /* the following is a limited try to support programs, that assume that
  219.        * st_dev is always valid */
  220.       f->f_stb.st_dev = (dev_t)(long)(f->f_fh->fh_Type); /* truncate to 16 bit */
  221.       /* yet another kludge.. if we call this with different descriptors, we
  222.        * should get different inode numbers.. grmpf.. */
  223.       f->f_stb.st_ino = (ino_t)~(long)(f->f_fh);
  224.       f->f_stb.st_nlink = 1; /* for now no problem.. 2.0... */
  225.       /* len could be -1, if the device doesn't allow seeking.. */
  226.       f->f_stb.st_size = len >= 0 ? len : 0;
  227.       f->f_stb.st_atime =  
  228.       f->f_stb.st_mtime =
  229.       f->f_stb.st_ctime = syscall (SYS_time, 0);
  230.     }
  231.  
  232.   /* try to find out block size of device, hey postman, it's packet-time
  233.    * again:-)) */
  234.   /* make sure, the packet is not in use anymore */
  235.   __wait_packet(&f->f_sp);
  236.  
  237.   /* clear the info-structure. Since this packet is used by the console
  238.    * handler to transmit the window pointer, it actually answers the
  239.    * request, but doesn't set the not used fields to 0.. this gives HUGE
  240.    * block lengths :-)) */
  241.   bzero (info, sizeof(*info));
  242.   SendPacket1(f,__rwport,ACTION_DISK_INFO,CTOBPTR(info));
  243.   __wait_packet(&f->f_sp);
  244.  
  245.   f->f_stb.st_blksize = 0;
  246.   if (LastResult (f) && info->id_BytesPerBlock)
  247.     {
  248.       f->f_stb.st_blksize = info->id_BytesPerBlock;
  249.       if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(f->f_stb.st_mode))
  250.     f->f_stb.st_blksize *= ix.ix_fs_buf_factor;
  251.       if (! f->f_stb.st_blocks) 
  252.     f->f_stb.st_blocks = ((f->f_stb.st_size + info->id_BytesPerBlock - 1) 
  253.                     / info->id_BytesPerBlock);
  254.     }
  255.  
  256.   if (! f->f_stb.st_blksize) 
  257.     {
  258.       f->f_stb.st_blksize = 512;
  259.       f->f_stb.st_blocks = (f->f_stb.st_size + 511) >> 9;
  260.     }
  261.  
  262. end:
  263.   /* reset error of packet. write() would fail if not */
  264.   LastResult(f) = 0;
  265.  
  266.   __release_file (f);
  267.   syscall (SYS_sigsetmask, omask);
  268.   return 0;
  269. }
  270.